/* ---------------------------------------------------------------------
 *
 * -- Privacy-preserving Sharing of Sensitive information Toolkit (PSST)
 *    (C) Copyright 2010 All Rights Reserved
 *
 * -- PSST routines -- Version 1.0.1 -- April, 2010
 * IBE_APSI corresponds to protocol IBE-APSI in the paper
 *
 * Author         : Yanbin Lu
 * Security and Privacy Research Outfit (SPROUT),
 * University of California, Irvine
 *
 * -- Bug report: send email to yanbinl@uci.edu
 * ---------------------------------------------------------------------
 *
 * -- Copyright notice and Licensing terms:
 *
 *  Redistribution  and  use in  source and binary forms, with or without
 *  modification, are  permitted provided  that the following  conditions
 *  are met:
 *
 * 1. Redistributions  of  source  code  must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce  the above copyright
 *    notice,  this list of conditions, and the  following disclaimer in
 *    the documentation and/or other materials provided with the distri-
 *    bution.
 * 3. The name of the University,  the SPROUT group,  or the names of its
 *    authors  may not be used to endorse or promote products deri-
 *    ved from this software without specific written permission.
 *
 * -- Disclaimer:
 *
 * THIS  SOFTWARE  IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,  INDIRECT, INCIDENTAL, SPE-
 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO,  PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEO-
 * RY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  (IN-
 * CLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "ibe_apsi_server.h"
#include "crypto_tool.h"
#include "basic_tool.h"
#include "pbc/pbc.h"
#include "mpz_tool.h"

IBE_APSI_Server::IBE_APSI_Server()
{
}

void IBE_APSI_Server::LoadData()
{
  m_set.clear();
  m_rawset.clear();

  ifstream infile(m_strInputFile.c_str());
  if (!infile)
	{
	  cerr<<"open "<<m_strInputFile<<" error"<<endl;
	  return;
	}
  string element;
  while (getline(infile, element) && infile.good())
	{
	  m_rawset.push_back(element);
	  mpz_t * e = Memreuse::New();
	  string h = CryptoTool::Hash(element);
	  MpzTool::Mpz_from_string(e, h);
	  m_set.push_back(e);
	}
}

void IBE_APSI_Server::Setup(int nbits)
{
  char param[1024];
  ifstream infile("ibe.priv");
  if (!infile)
	{
	  cerr<<"open "<<m_strInputFile<<" failed"<<endl;
	  return;
	}
  size_t count, n;
  infile.read((char *)&count, sizeof(count));
  if (!count)
	{
	  pbc_die("input error");
	}
  infile.read(param, count);
  m_pairing = (pairing_t *) malloc(sizeof(pairing_t));
  pairing_init_set_buf(*m_pairing, param, count);
  
  unsigned char * data;
  m_P = Memreuse::NewElement();
  element_init_G1(*m_P, *m_pairing);
  infile.read((char *)&n, sizeof(n));
  data = (unsigned char *) malloc(n);
  infile.read((char *)data, n);
  element_from_bytes(*m_P, data);
  delete data;

  m_Q = Memreuse::NewElement();
  element_init_G1(*m_Q, *m_pairing); 
  infile.read((char *)&n, sizeof(n));
  data = (unsigned char *) malloc(n);
  infile.read((char *)data, n);
  element_from_bytes(*m_Q, data);
  delete data;

  m_z = Memreuse::NewElement();
  element_init_Zr(*m_z, *m_pairing); 
  m_R = Memreuse::NewElement();
  element_init_G1(*m_R, *m_pairing);  
  m_h = Memreuse::NewElement();
  element_init_G2(*m_h, *m_pairing); 
  m_t = Memreuse::NewElement();
  element_init_GT(*m_t, *m_pairing);

  LoadData();
  rn.Initialize(nbits);
}

void IBE_APSI_Server::Initialize(int nbits)
{
  char hash[1024];
  size_t nlen;
  size_t n = pairing_length_in_bytes_G1(*m_pairing);
  unsigned char * data = (unsigned char *)malloc(n);
  element_random(*m_z);
  element_pow_zn(*m_R, *m_P, *m_z);
  element_to_bytes(data, *m_R);
  m_output.push_back(string((const char *)data, n));
  delete data;

  n = pairing_length_in_bytes_GT(*m_pairing);
  data = (unsigned char *)malloc(n);
  for (size_t i = 0; i < m_set.size(); i++)
	{
	  MpzTool::Char_from_mpz(hash, nlen, 1024, m_set[i]);

	  element_from_hash(*m_h, hash, nlen);
	  pairing_apply(*m_t, *m_Q, *m_h, *m_pairing);
	  element_pow_zn(*m_t, *m_t, *m_z);
	  element_to_bytes(data, *m_t);
	  m_toutput.push_back(CryptoTool::Hash(data, n));
	}

}

void IBE_APSI_Server::PublishData(vector<string>& output)
{
  output.insert(output.end(), m_toutput.begin(), m_toutput.end());
}

int IBE_APSI_Server::OnRequest1(const vector<string>& input)
{
 return 0;
}
